﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using Utilities;
using Communication;
using System.Net.NetworkInformation;

namespace TCPServer
{
    class Client
    {
        public const string MESSAGE_END = "<EOF>";
        private const int mTimeout = 5000;
        private IPAddress serverIP = IPAddress.Parse("5.48.197.212");// real ip "134.225.180.164" local host "127.0.0.1" hamachi "5.48.197.212"
        private const int SERVER_PORT = 3000;
        private int listeninPort = 16000;
        IPEndPoint serverEndPoint;

        private string authenticationString;
        private bool isAuthenticated = false;
        public bool IsAuthenticated { get { return isAuthenticated; } }

        private AsyncReceiver receiver;
        private AsyncSender sender;

        public ManualResetEvent authenticationDone = new ManualResetEvent(false);
        
        public Client(string username, string password, IPAddress ip)
        {
            this.serverIP = ip;
            this.CreateNewClient();
            if (username != null && password != null)
            {
                Change(username, password);
            }
            //check if the received respone is equal to true. then Authentication = true;
        }

        public Client(IPAddress ip)
        {
            this.serverIP = ip;
            CreateNewClient();
        }

        private void CreateNewClient()
        {
            while (!IPUtil.IsPortAvaliable(listeninPort) && listeninPort < IPEndPoint.MaxPort)
            {
                listeninPort++;
            }
            //receiver listening from any IP incomming to the speciefic port
            // further update shoud limit it to know IP addresses;
            receiver = new AsyncReceiver(new IPEndPoint(IPAddress.Any, listeninPort)); // listen to this PORT! Server must send here
            receiver.newMessage += new AsyncReceiver.TickHandler(MessageReceived);

            serverEndPoint = new IPEndPoint(serverIP, SERVER_PORT);
            sender = new AsyncSender(serverEndPoint);
        }

        public void Change(string username, string password)
        {
            authenticationDone.Reset();
            //password = SHA1Encryption.EncodePasswordToBase64(password);
            authenticationString = "<u>" + username + "<p>" + password;

            this.sender.Send("<aut>" + authenticationString + "<port>" + listeninPort.ToString() + "<m><EOF>");
            authenticationDone.WaitOne(mTimeout);
        }

        public void Send(string message)
        {
            sender.Send(authenticationString + "<m>" + message);
        }

        private void MessageReceived(AsyncReceiver res, MessageEvent msg)
        {
            string message = msg.Message;
           
            Console.WriteLine("Time on message arrival: " + DateTime.Now.ToString()); 
            Console.WriteLine("With MS "+DateTime.Now.Millisecond);
            //Console.WriteLine("Message received: " + message);
            if (message.Equals("<true><EOF>"))
            {
                this.isAuthenticated = true;
                authenticationDone.Set();
            }
        }
    }
}
